
#include "iodev.h"



 char keytable0[0x80] = {
		0,   0,   '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,   0,
		'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']', 0,   0,   'A', 'S',
		'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', '`',   0,   '\\', 'Z', 'X', 'C', 'V',
		'B', 'N', 'M', ',', '.', '/', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
		'2', '3', '0', '.', 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0x5c, 0,  0,   0,   0,   0,   0,   0,   0,   0,   0x5c, 0,  0
	};
 char keytable1[0x80] = {
		0,   0,   '!', 0x22, '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0,   0,
		'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0,   0,   'A', 'S',
		'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',   0,   '|', 'Z', 'X', 'C', 'V',
		'B', 'N', 'M', '<', '>', '?', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
		'2', '3', '0', '.', 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   '_', 0,   0,   0,   0,   0,   0,   0,   0,   0,   '|', 0,   0
	};





void wait_KBC_sendready (void ){ 
	for (;;){ 
		if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY ) ==0) {  //等待keyboard controller(KBC)反馈信息 ，当反馈数据的第二位为0时表示KBC准备完毕
			break ;
		 }
	}
}

//等待键盘控制器初始化，写入鼠标模式
void init_keyboard (void){
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD,KEYCMD_WRITE_MODE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT,KBC_MODE);  //0x47 表示利用鼠标模式
}


//在键盘控制器中启用鼠标
void enable_mouse (void ){ 
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
}


int mouse_decode (MOUSE_INFO * info , unsigned char data ) {
	//char s [50] ;
	if (info->phase == 0 ) {
		if (data ==0xfa) { // 鼠标KBC初始化完成以后第一次会返回0xfa ，我们要忽略它 
			info->phase =1 ;
		}/*else { 
			sprintf(s,"keyboard ,data = %02x " ,data);
			boxfill8(btinfo->vram, btinfo->scrnx, COL8_000000, 0, 100, 32 * 8 - 1,100+ 15);
			putchars8(btinfo->vram,btinfo->scrnx,0,0,COL8_FFFFFF,s) ;
			info->phase =1;
		}*/
		return 0;
	}
	if (info->phase ==1) {
		 /**鼠标第一个数据高4位范围从0x0-0x3变化（表示鼠标移动 ，0表示不动）,低四位8-F （表示按键信息 ，8表示没有按键）*/
		if ((data & 0xc8) ==0x08) { //判断是不是第一个数据  ，用于纠正偶尔发生的错误，否则第123个数据就错位了 
			info->buf[0] = data ;
			info->phase =2 ;
		}
		return 0 ;
	}
	if (info->phase ==2) { 
		info->buf[1] = data ;
		info->phase =3;
		return 0 ;
	}
	if (info->phase ==3) { 
		info->buf[2] = data ; //此时3字节数据就接受完成了 (3字节数据表示一次鼠标事件)
		info->phase =1 ; 
		info->btn = info->buf[0] & 0x07 ; //取低4位信息的低3位 ,001表示左键，010右键，100滚轮（低4位的最高位一定是1 (8-F)）
		info->x = info->buf[1] ;
		info->y = info->buf[2] ;
		if ( (info->buf[0] & 0x10)!=0){ //判断高4位的第一位是不是0  
			info->x |= 0xffffff00 ; //将其他位都设为0或者1就行了 , (不明白为什么，一旦不这样鼠标乱飞)
		}
		if ( (info->buf[0] & 0x20)!=0){ //判断高4位的第二位是不是0  
			info->y |= 0xffffff00 ;
		}
		info->y = -info->y ; // 取反是因为鼠标与屏幕y方向相反
		return 1;
	}
	return 0 ;

}
  
  